package com.homedo.microservice.open.service.gateway.manager.web.gateway.service;

import com.google.common.collect.Lists;
import com.homedo.common.bean.data.enums.ResponseEnum;
import com.homedo.common.bean.vo.Pagination;
import com.homedo.common.bean.vo.context.UserContext;
import com.homedo.common.dao.bean.po.base.BasePo;
import com.homedo.common.dao.bean.po.enhanced.base.BaseEnhanced;
import com.homedo.common.exception.HomedoException;
import com.homedo.common.service.BaseService;
import com.homedo.common.util.Detect;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.enums.forrouteservice.StatusEnum4RouteService;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.Route;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteService;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteServiceUrl;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.RouteVersion;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.AlertUserEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.AlertUserRouteServiceEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteServiceEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.po.enhanced.RouteServiceUrlEnhanced;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.bean.query.RouteServiceQuery;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.persistence.dao.RouteDao;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.persistence.dao.RouteServiceDao;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.persistence.dao.RouteServiceUrlDao;
import com.homedo.microservice.open.service.gateway.manager.web.gateway.persistence.dao.RouteVersionDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 作者 jgshun
 * @date 创建时间 2018年09月18日 11时30分20秒
 */
@Service
public class RouteServiceService extends BaseService<RouteService> {
    @Autowired
    private RouteServiceDao routeServiceDao;
    @Autowired
    private RouteServiceUrlService routeServiceUrlService;
    @Autowired
    private RouteDao routeDao;
    @Autowired
    private RouteVersionDao routeVersionDao;
    @Autowired
    private RouteServiceUrlDao routeServiceUrlDao;
    @Autowired
    private AlertUserRouteServiceService alertUserRouteServiceService;


    @Override
    public List<RouteServiceEnhanced> getEnhanceds(List<?> ids, UserContext userContext) {
        List<RouteService> routeServices = routeServiceDao.getListByIds(ids, RouteService.class);

        if (!Detect.notEmpty(routeServices)) {
            return null;
        }
        List<RouteServiceEnhanced> routeServiceEnhanceds = this.convent2Enhanceds(routeServices);

        this.appendEnhancedCommons(routeServiceEnhanceds, userContext);

        return routeServiceEnhanceds;
    }


    @Override
    public List<RouteServiceEnhanced> getEnhanceds4Active(List<?> ids, UserContext userContext) {
        List<RouteService> routeServices = routeServiceDao.getListByIdsGreaterThanMark0(ids, RouteService.class);

        if (!Detect.notEmpty(routeServices)) {
            return null;
        }
        List<RouteServiceEnhanced> routeServiceEnhanceds = this.convent2Enhanceds(routeServices);

        this.appendEnhancedCommons(routeServiceEnhanceds, userContext);

        return routeServiceEnhanceds;
    }


    @Override
    public List<RouteServiceEnhanced> convent2Enhanceds(List<? extends BasePo> pos) {
        List<RouteService> routeServices = (List<RouteService>) pos;
        List<RouteServiceEnhanced> routeServiceEnhanceds = Lists.newArrayList();
        routeServices.forEach(e -> routeServiceEnhanceds.add(new RouteServiceEnhanced(e)));
        return routeServiceEnhanceds;
    }

    public List<RouteServiceEnhanced> appendEnhancedCommons(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
        List<RouteServiceEnhanced> routeServiceEnhanceds = (List<RouteServiceEnhanced>) enhancedItems;

        this.appendRouteServiceUrlEnhanceds(routeServiceEnhanceds, userContext);

        return routeServiceEnhanceds;
    }

    public RouteServiceEnhanced appendRouteServiceUrlEnhanceds(RouteServiceEnhanced routeServiceEnhanced, UserContext userContext) {
        return this.appendRouteServiceUrlEnhanceds(Lists.newArrayList(routeServiceEnhanced), userContext).get(0);
    }


    public List<RouteServiceEnhanced> appendRouteServiceUrlEnhanceds(List<RouteServiceEnhanced> routeServiceEnhanceds, UserContext userContext) {
        List<String> serviceIds = routeServiceEnhanceds.stream().map(RouteServiceEnhanced::getId).collect(Collectors.toList());

        List<RouteServiceUrlEnhanced> routeServiceUrlEnhanceds = routeServiceUrlService.getEnhanceds4Services(serviceIds, userContext);

        if (!Detect.notEmpty(routeServiceUrlEnhanceds)) {
            return routeServiceEnhanceds;
        }

        this.appendRouteServiceUrlEnhanceds(routeServiceEnhanceds, routeServiceUrlEnhanceds, userContext);

        return routeServiceEnhanceds;
    }

    public RouteServiceEnhanced appendAlertUserEnhanceds(RouteServiceEnhanced routeServiceEnhanceds, UserContext userContext) {
        return this.appendAlertUserEnhanceds(Lists.newArrayList(routeServiceEnhanceds), userContext).get(0);
    }

    public List<RouteServiceEnhanced> appendAlertUserEnhanceds(List<RouteServiceEnhanced> routeServiceEnhanceds, UserContext userContext) {
        List<String> ids = routeServiceEnhanceds.stream().map(RouteServiceEnhanced::getId).collect(Collectors.toList());
        List<AlertUserRouteServiceEnhanced> alertUserRouteServiceEnhanceds = alertUserRouteServiceService.getEnhancedsByServiceIds(ids, userContext);
        if (!Detect.notEmpty(alertUserRouteServiceEnhanceds)) {
            return routeServiceEnhanceds;
        }

        alertUserRouteServiceEnhanceds = alertUserRouteServiceService.appendAlertUserEnhanced(alertUserRouteServiceEnhanceds, userContext);
        this.appendAlertUserEnhanceds(routeServiceEnhanceds, alertUserRouteServiceEnhanceds, userContext);

        return routeServiceEnhanceds;
    }

    private void appendAlertUserEnhanceds(List<RouteServiceEnhanced> routeServiceEnhanceds, List<AlertUserRouteServiceEnhanced> alertUserRouteServiceEnhanceds, UserContext userContext) {
        routeServiceEnhanceds.forEach(e -> {
            this.appendAlertUserEnhanceds(e, alertUserRouteServiceEnhanceds, userContext);
        });
    }

    private void appendAlertUserEnhanceds(RouteServiceEnhanced routeServiceEnhanced, List<AlertUserRouteServiceEnhanced> alertUserRouteServiceEnhanceds, UserContext userContext) {
        List<AlertUserEnhanced> alertUserEnhanceds = Lists.newArrayList();
        alertUserRouteServiceEnhanceds.forEach(e -> {
            if (e.getAlertUserEnhanced() != null && routeServiceEnhanced.getId().equals(e.getRouteServiceEnhanced().getId())) {
                alertUserEnhanceds.add(e.getAlertUserEnhanced());
            }
        });
        routeServiceEnhanced.setAlertUserEnhanceds(alertUserEnhanceds);
    }

    private void appendRouteServiceUrlEnhanceds(List<RouteServiceEnhanced> routeServiceEnhanceds, List<RouteServiceUrlEnhanced> routeServiceUrlEnhanceds, UserContext userContext) {
        routeServiceEnhanceds.forEach(e -> {
            this.appendRouteServiceUrlEnhanceds(e, routeServiceUrlEnhanceds, userContext);
        });
    }

    private void appendRouteServiceUrlEnhanceds(RouteServiceEnhanced routeServiceEnhanced, List<RouteServiceUrlEnhanced> routeServiceUrlEnhanceds, UserContext userContext) {
        List<RouteServiceUrlEnhanced> curRouteServiceUrlEnhanceds = Lists.newArrayList();

        routeServiceUrlEnhanceds.forEach(e -> {
            if (e.getRouteServiceEnhanced().getId().equals(routeServiceEnhanced.getId())) {
                curRouteServiceUrlEnhanceds.add(e);
            }
        });

        routeServiceEnhanced.setRouteServiceUrlEnhanceds(curRouteServiceUrlEnhanceds);
    }

    public Pagination<RouteServiceEnhanced> getPagination(RouteServiceQuery routeServiceQuery, Pagination<RouteServiceEnhanced> pagination, UserContext userContext) {
        Pagination<RouteService> routeServicePagination = routeServiceDao.getPagination(routeServiceQuery, pagination.copy());

        pagination.setCount(routeServicePagination.getCount());

        if (!Detect.notEmpty(routeServicePagination.getItems())) {
            return pagination;
        }

        pagination.setItems(this.convent2Enhanceds(routeServicePagination.getItems()));

        return pagination;
    }

    public RouteService addRouteService(RouteService routeService, UserContext userContext) {
        this.checkAdd(routeService);

        routeService.setCreateTime(new Date());
        routeService.setUpdateTime(new Date());

        return routeServiceDao.saveSelective(routeService);
    }

    private void checkAdd(RouteService routeService) {
        if (!Detect.notEmpty(routeService.getId()) || !Detect.notEmpty(routeService.getApplicationName())
                || !Detect.notEmpty(routeService.getComment()) || routeService.getStatus() == null
                || !Detect.notEmpty(routeService.getHealthUrl())) {
            throw new HomedoException(ResponseEnum.PARAM_ERROR);
        }
    }

    public void deleteRouteService(String id, UserContext userContext) {
        List<Route> routes = routeDao.getListByKeyValues(Route.FIELD_SERVICEID, Lists.newArrayList(id), Route.class);
        if (Detect.notEmpty(routes)) {
            List<String> ids = routes.stream().map(Route::getId).collect(Collectors.toList());
            throw new HomedoException("[已绑定路由,请先解绑:" + ids + "]");
        }

        List<RouteVersion> routeVersions = routeVersionDao.getListByKeyValues(RouteVersion.FIELD_SERVICEID, Lists.newArrayList(id), RouteVersion.class);

        if (Detect.notEmpty(routeVersions)) {
            List<String> ids = routeVersions.stream().map(RouteVersion::getRouteId).collect(Collectors.toList());
            throw new HomedoException("[已绑定版本路由,到路由下:" + ids + ",请先解绑]");
        }

        RouteServiceUrl routeServiceUrlRecord = new RouteServiceUrl();
        routeServiceUrlRecord.setServiceId(id);
        routeServiceUrlDao.delete(routeServiceUrlRecord);//删除后端服务地址

        routeServiceDao.deleteById(id);
    }

    public RouteService updateRouteService(String id, String healthUrl, String comment, Short status, UserContext userContext) {
        RouteService routeService = routeServiceDao.getById(id);

        if (Detect.notEmpty(healthUrl)) {
            routeService.setHealthUrl(healthUrl);
        }

        if (Detect.notEmpty(comment)) {
            routeService.setComment(comment);
        }

        if (status != null && StatusEnum4RouteService.getStatusEnumByCode(status) != null) {
            routeService.setStatus(status.intValue());
        }

        routeService.setUpdateTime(new Date());

        routeServiceDao.updateByPrimaryKeySelective(routeService);

        return routeService;
    }


}
